﻿using System;
using System.Collections.Generic;
using System.Text;
using Noea.TogSim.Model.Interfaces;

namespace Noea.TogSim.Model.Train.LocoDriver.States
{
    public class RunningState : LocoState
    {
        public RunningState()
            : base()
        {
            base._description = "Running";
        }
        public override LocoState Handle(LocoDriver_StPattern ld)
        {
            if (TrackIsBlocked(ld))
            {
                return StateFactory.StoppingState;
            }
            else if (Math.Abs(ld.Train.ActualSpeed - ld.Train.RequestedSpeed) > 0.2)
            {
                return StateFactory.AccelerateState;
            }
            else
            {
                ld.Train.ActualSpeed = ld.Train.RequestedSpeed;
                return this;
            }
        }

        internal enum Direction
        {
            Forward, 
            Backwards
        }

        private Direction GetTrainDirection(ITrainSet train)
        {
            if (train.CurrentTrack.Id > train.PreviousTrack.Id)
            {
                return Direction.Forward;
            }

            return Direction.Backwards;
        }

        private bool TrackIsBlocked(LocoDriver_StPattern ld)
        {
            int brakeLength = 5;
            int counter = 0;

            if (ld.Train.PreviousTrack == null)
                return false;

            Direction trainDirection = GetTrainDirection(ld.Train);

            ITrack nextTrack = ld.Train.CurrentTrack;

            while (true)
            {
                if (nextTrack == null || nextTrack.Previous == null || nextTrack.Next == null)
                    break;

                if (trainDirection == Direction.Forward)
                {
                    nextTrack = nextTrack.Next;
                }
                else
                {
                    nextTrack = nextTrack.Previous;
                }
                
                if (nextTrack.IsBlocked)
                    return true;

                if (counter++ >= brakeLength)
                    break;
            }

            return false;
        }
    }
}
